package com.ytz.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ytz.config.WxPayConfig;
import com.ytz.entity.OrderInfo;
import com.ytz.enums.wx.WxApiType;
import com.ytz.service.IOrderInfoService;
import com.ytz.service.IWxPaymentService;
import com.ytz.vo.BaseResult;
import com.ytz.vo.CodeEnum;
import com.ytz.vo.PayInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;

@Slf4j
@Service
public class WxPaymentServiceImpl implements IWxPaymentService {
    @Autowired
    private IOrderInfoService iOrderInfoService;
    @Autowired
    WxPayConfig wxPayConfig;
    @Autowired
    CloseableHttpClient wxPayClient;
    @Transactional(rollbackFor = Exception.class)
    @Override
    public BaseResult nativePay(String orderNo) throws Exception {

        log.info("开始native下单");
        //1.根据订单编号查询订单信息
        OrderInfo orderInfo = iOrderInfoService.findByOrderNo(orderNo);
        if (orderInfo == null) {
            return BaseResult.error(CodeEnum.ORDER_ERROR);
        }
        if(orderInfo!=null& !StringUtils.isEmpty(orderInfo.getCodeUrl())){
            //直接返回二维码
            PayInfoVO payInfoVO=new PayInfoVO();
            payInfoVO.setCodeUrl(orderInfo.getCodeUrl());
            payInfoVO.setOrderNo(orderInfo.getOrderNo());
            return BaseResult.ok(payInfoVO);
        }


        //2.调用统一下载api https://api.mch.weixin.qq.com/v3/pay/transactions/native
        HttpPost httpPost = new HttpPost(wxPayConfig.getDomain().concat(WxApiType.NATIVE_PAY.getType()));

        //3.组装请求参数
        HashMap<String, Object> paramsMap = new HashMap<>();
        paramsMap.put("appid", wxPayConfig.getAppid());// 应用id
        paramsMap.put("mchid", wxPayConfig.getMchId());// 商户id
        paramsMap.put("description", "test");// 商品描述
        paramsMap.put("out_trade_no", orderInfo.getOrderNo());// 订单编号
        paramsMap.put("notify_url", wxPayConfig.getDomain().concat(wxPayConfig.getNotifyDomain()));// 通知地址
        HashMap<String, Object> amountMap = new HashMap<>();
        amountMap.put("total", orderInfo.getTotalFee());
        paramsMap.put("amount", amountMap);// 订单金额

        //4.将参数转化为json字符串
        String jsonString = JSON.toJSONString(paramsMap);
        log.info("Native 下单参数===" + jsonString);

        //5.准备消息body
        StringEntity entity = new StringEntity(jsonString, "UTF-8");
        entity.setContentType("application/json");//声明json数据
        httpPost.setEntity(entity);

        //6.准备请求头
        httpPost.setHeader("Accept", "application/json");

        //7完成签名并执行请求
        CloseableHttpResponse response = wxPayClient.execute(httpPost);
        try {
            //8.拿出body响应体
            String bodyString = EntityUtils.toString(response.getEntity());
            //9.获取响应状态码
            int statusCode = response.getStatusLine().getStatusCode();
            //10.判断响应码
            if (statusCode == 200) {
                HashMap<String,String> responseMap = JSON.parseObject(bodyString, HashMap.class);
                //11.取出code_url
                String code_url = responseMap.get("code_url");
                //更新code_url
                iOrderInfoService.saveCodeUrl(orderInfo.getId(),code_url);

                PayInfoVO payInfoVO=new PayInfoVO();
                payInfoVO.setCodeUrl(code_url);
                payInfoVO.setOrderNo(orderInfo.getOrderNo());
                return BaseResult.ok(payInfoVO);

            } else {
                log.error("Native 下单失败，响应码为" + statusCode + "返回结果为" + bodyString);
                return BaseResult.error(CodeEnum.PAYMENT_ERROR);
            }


        } finally {
            response.close();
        }


    }
}
